package com.wp.targetOffer;

/**
 * Created by 王萍 on 2017/7/28 0028.
 */

import java.util.stream.Stream;

/**
 * 大家都知道斐波那契数列，现在要求输入一个整数n，请你输出斐波那契数列的第n项。
 * n<=39
 */
//用循环不要用递归，递归有很多重复计算。比如求f(4)=f(3)+f(2),f(3)=f(2)+f(1)，这里就计算了两次f(2)。
public class 斐波那契数列 {

    public static void main(String[] args) {
        System.out.println(Fibonacci(11));
        System.out.println(Fibonacci2(11));
//        Fibonacci3(11);
        System.out.println(Fibonacci4(11));
        System.out.println(Fibonacci5(11));
    }

    public static int Fibonacci(int n) {
        if (n <= 1) {
            return n;
        } else {
            int before = 0, after = 1;
            for (int i = 2; i < n; i++) {
                after += before;
                before = after - before;
            }
            return after + before;
        }
    }

    public static int Fibonacci2(int n) {
        int before = 0, after = 1;
        while (n-- != 0) {
            after += before;
            before = after - before;
        }
        return before;
    }

    public static void Fibonacci3(int n) {

        Stream.iterate(new int[]{0, 1}, t -> new int[]{t[1], t[0] + t[1]})
//                .limit(n)
                .map(t -> t[0])
                .forEach(System.out::println);
    }

    public static int Fibonacci4(int n) {
        if (n <= 1) return n;
        return Fibonacci4(n - 1) + Fibonacci(n - 2);
    }

    public static int[] result;

    public static int Fibonacci5(int n) {
        result = new int[n+1];
        for (int i = 0; i <= n; i++) {
            result[i] = -1;
        }
        return doFib(n);
    }

    private static int doFib(int n) {
        if ((n <= 1)) return n;
        if (result[n] >= 0) return result[n];
        result[n] = doFib(n-1) + doFib(n - 2);
        return result[n];
    }

}
